home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d7 / faxctrl.arc / FHOST.SLT < prev    next >
Text File  |  1990-12-28  |  21KB  |  909 lines

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. //   H O S T . S L T
  4. //
  5. //   Copyright (C) 1988 PTel and Colin Sampaleanu
  6. //
  7. //   This is a Host Mode for Telix, written as a script file.
  8. //   To configure Host Mode parameters such as passwords, run the 'HCONFIG'
  9. //   script. That script is run automatically if the Host Mode configuration
  10. //   file 'HOST.CNF' is missing.
  11. //
  12. //   This script will only work with Hayes compatible modems, but may be
  13. //   modified for operation with other modems.
  14. //
  15. //////////////////////////////////////////////////////////////////////////////
  16.  
  17. // Parameters which can be configured
  18.  
  19. str pass1[8] = "pass1",                 // The level 1 pass
  20.     pass2[8] = "pass2",                 // The level 2 (Sysop) pass
  21.     shellpass[8] = "shell",             // the pass to enter the Remote Shell
  22.     shutpass[8] = "shut",               // the pass to shut down the Host Mode
  23.     host_downloads[64],                 // where users may download from
  24.     host_uploads[64];                   // where uploaded files go
  25. int direct_connect = 0;
  26.  
  27. str current_caller[31],                 // storage of current caller's name
  28.     conn300[] = "CONNECT^M",            // modem result messages for bauds
  29.     conn1200[] = "CONNECT 1200",
  30.     conn2400[] = "CONNECT 2400",
  31.     conn9600[] = "CONNECT 9600",
  32.     conn19200[] = "CONNECT 19200";
  33. int finished_caller,                    // set to TRUE when must return to top
  34.     local_mode,                         // set to TRUE when local test mode
  35.     access_level,                       // access level of current caller
  36.     carrier_counts = 1,                 // TRUE if should watch Carrier signal
  37.     already_connected = 0,
  38.     exit_requested = 0,                 // set to TRUE if Sysop has pressed Esc
  39.     connection_lost = 0,                // set to TRUE when carrier lost
  40.     kill_user = 0;                      // set to TRUE when user must be purged
  41.  
  42. int old_scr_chk_key,                    // storage for some system variables
  43.     old_cisb_auto,                      // which we have to modify and put
  44.     old_zmod_auto,                      // back to what they were when done
  45.     old_sound;
  46. str old_down_dir[64],
  47.     old_up_dir[64];
  48.  
  49. //////////////////////////////////////////////////////////////////////////////
  50. //////////////////////////////////////////////////////////////////////////////
  51.  
  52. main()
  53.  
  54. {
  55.  int c;
  56.  int t;
  57.  
  58.  clear_scr();
  59.  
  60.  if (read_host_config_file() == -1)
  61.   {
  62.    prints("Unable to read HOST.CNF...");
  63.    prints("Running HCONFIG, the Host Mode configuration script.^M^J");
  64.    call("HCONFIG");
  65.    if (read_host_config_file() == -1)
  66.     {
  67.      prints("Still unable to read HOST.CNF. Aborting Host Mode.^M^J");
  68.      return -1;
  69.     }
  70.   }
  71.  
  72.  if (!check_directories())
  73.   {
  74.    prints("Either the upload or download directory as defined in the HOST.CNF file");
  75.    prints("doesn't exist. Either create the missing directory with the DOS 'MKDIR'");
  76.    prints("command, or run the HCONFIG script to redefine what directories to use.");
  77.    prints("Aborting Host Mode.");
  78.    return -1;
  79.   }
  80.  
  81.  old_scr_chk_key = _scr_chk_key;
  82.  _scr_chk_key = 0;
  83.  old_cisb_auto = _cisb_auto;
  84.  _cisb_auto = 0;
  85.  old_zmod_auto = _zmod_auto;
  86.  _zmod_auto = 0;
  87.  old_sound = _sound_on;
  88.  _sound_on = 0;
  89.  old_down_dir = _down_dir;
  90.  _down_dir = host_uploads;   // these are reversed because we are now the Host
  91.  old_up_dir = _up_dir;
  92.  _up_dir = host_downloads;   // these are reversed because we are now the Host
  93.  
  94.  usagelog("HOST.LOG");
  95.  
  96.  if (direct_connect)
  97.   carrier_counts = 0;
  98.  else
  99.   carrier_counts = 1;
  100.  
  101.  if (!direct_connect && carrier())
  102.   already_connected = 1;
  103.  
  104.  if (!direct_connect && !already_connected)
  105.   {
  106.    prints("Initializing modem");
  107.    cputs_tr(_auto_ans_str);
  108.   }
  109.  
  110.  while (1)
  111.   {
  112.    finished_caller = kill_user = 0;
  113.  
  114.    if (direct_connect)
  115.     carrier_counts = 0;
  116.    else
  117.     carrier_counts = 1;
  118.  
  119.    if (!direct_connect)
  120.     {
  121.  
  122.      clear_scr();
  123.      t = timer_start(700);
  124.  
  125.      prints("^M^JHost Mode: Waiting for call...");
  126.      prints("(Press Esc to exit, or 'L' for local test mode).^M^J");
  127.  
  128.      do
  129.       {
  130.        if (carrier())
  131.         {
  132.          local_mode = 0;
  133.          break;
  134.         }
  135.  
  136.        if (time_up(t)) {
  137.           Exittelix (0);
  138.        }
  139.  
  140.        c = inkey();
  141.        if (c)
  142.         {
  143.          if (c == 27)
  144.           {
  145.            exit_requested = 1;
  146.            break;
  147.           }
  148.          else if (c == 'l' || c == 'L')               // local teswt mode
  149.           {
  150.            prints("Local test mode entered");
  151.            local_mode = 1;
  152.            carrier_counts = 0;
  153.           }
  154.         }
  155.       }
  156.      while (toupper(c) != 'L');
  157.      timer_free(t);
  158.     }
  159.  
  160.    if (!exit_requested)
  161.     {
  162.      prints("Incoming call. Sysop: press Esc to exit, or END to terminate user.");
  163.  
  164.      do_one_caller();
  165.      if ((connection_lost || kill_user) && carrier_counts && carrier())
  166.       hangup();             // make sure nobody sneaks in
  167.     }
  168.    already_connected = 0;
  169.    if (exit_requested)
  170.     {
  171.      if (!carrier() && !direct_connect)
  172.       cputs_tr(_mdm_init_str);
  173.      _scr_chk_key = old_scr_chk_key;
  174.      _cisb_auto = old_cisb_auto;
  175.      _zmod_auto = old_zmod_auto;
  176.      _sound_on = old_sound;
  177.      _down_dir = old_down_dir;
  178.      _up_dir = old_up_dir;
  179.      prints("^M^JHost mode script finished.");
  180.      usagelog("*CLOSE*");
  181.      return 1;
  182.     }
  183.   }
  184. }
  185.  
  186. //////////////////////////////////////////////////////////////////////////////
  187.  
  188. do_one_caller()
  189.  
  190. {
  191.  str strn[80],
  192.      fname[64];
  193.  int option,
  194.      status,
  195.      c, i, i2;
  196.  
  197.  access_level = 1;
  198.  
  199.  if (already_connected)
  200.   prints("Already Connected!");
  201.  else if (carrier_counts)
  202.   {
  203.    if (!determine_baud())
  204.     ;                          // do something else here if this is a problem
  205.   }
  206.  
  207.  delay(10);
  208.  type_file("LOGO.MSG");
  209.  
  210.  flushbuf();
  211.  while (1)
  212.   {
  213.    host_send("Please enter your full name: ");
  214.    host_input_strn(current_caller, 30);
  215.    host_send("^M^J");
  216.  
  217.    if (finished_caller)
  218.     return;
  219.  
  220.    if (strlen(current_caller) >= 5)
  221.     break;
  222.   }
  223.  
  224.  access_level = ask_for_pass(3, pass1, pass2);
  225.  
  226.  if (access_level)
  227.   ustamp("Logon by ", 1, 0);
  228.  else
  229.   ustamp("Failed logon attempt by ", 1, 0);
  230.  ustamp(current_caller, 0, 1);
  231.  
  232.  if (!access_level)
  233.   {
  234.    host_send("Goodbye!^M^J");
  235.    if (carrier_counts)
  236.     {
  237.      delay(10);
  238.      hangup();
  239.     }
  240.    return;
  241.   }
  242.  
  243.  type_file("WELCOME.MSG");
  244.  
  245.  while (1)
  246.   {
  247.    if (finished_caller)
  248.     return;
  249.  
  250.    host_send("^M^J[F]iles    [T]ype    [U]pload    [D]ownload    [G]oodbye   [?]^]");
  251.    host_input_strn(strn, 1);
  252.    option = toupper(subchr(strn, 0));
  253.    host_send("^M^J");
  254.  
  255.    if (option == 'F')                 // Files directory
  256.     {
  257.      if (access_level == 2)
  258.       {
  259.        host_send("Enter 'filespec' or press Return for *.*,^M^J: ");
  260.        host_input_strn(fname, 64);
  261.        host_send("^M^J");
  262.  
  263.        if (just_filename(fname))
  264.         {
  265.          strn = host_downloads;
  266.          strcat(strn, fname);
  267.         }
  268.        else
  269.         strn = fname;
  270.       }
  271.      else
  272.       {
  273.        strn = host_downloads;
  274.        strcat(strn, "*.*");
  275.       }
  276.        
  277.      if (local_mode)
  278.       show_directory(strn, 0, carrier_counts);
  279.      else
  280.       show_directory(strn, 1, carrier_counts);
  281.      host_send("^M^J");
  282.     }
  283.    else if (option == 'T')            // Type a file
  284.     {
  285.      host_send("Type what file? ");
  286.      host_input_strn(strn, 64);
  287.      host_send("^M^J");
  288.      if (access_level != 2)             // if access 1, name and ext only
  289.       fnstrip(strn, 3, fname);
  290.      else
  291.       fname = strn;
  292.  
  293.      if (just_filename(fname))
  294.       {
  295.        strn = host_downloads;
  296.        strcat(strn, fname);
  297.        fname = strn;
  298.       }
  299.  
  300.      if (!filefind(fname, 0, strn))
  301.       {
  302.        host_send("Unable to find ");
  303.        host_send(fname);
  304.        continue;
  305.       }
  306.  
  307.      type_file(fname);
  308.     }
  309.    else if (option == 'G')            // Goodbye (Hang-up)
  310.     {
  311.      host_send("^M^JGoodbye!^M^J");
  312.      Exittelix (0,1);
  313.      ustamp("User logged off.", 1, 1);
  314.      if (carrier_counts)
  315.       {
  316.        delay(10);
  317.        hangup();
  318.       }
  319.      return;
  320.     }
  321.    else if (option == 'U')            // User upload
  322.     {
  323.      option = host_get_prot();
  324.      if (!option)
  325.       continue;
  326.  
  327.      status = 1;
  328.      if (option == 'T' || option == 'M' || option == 'S' ||
  329.          option == 'Y' || option == 'Z' || option == 'E')
  330.       {
  331.        send_transfer_msg();
  332.        status = receive(option, "");
  333.       }
  334.      else
  335.       {
  336.        host_send("Upload what file? ");
  337.        host_input_strn(strn, 48);
  338.        host_send("^M^J");
  339.        if (!strn)
  340.         continue;
  341.        if (access_level != 2)             // if access 1, name and ext only
  342.         fnstrip(strn, 3, fname);
  343.        else
  344.         fname = strn;
  345.  
  346.        if (just_filename(fname))
  347.         {
  348.          strn = host_uploads;
  349.          strcat(strn, fname);
  350.          fname = strn;
  351.         }
  352.  
  353.        if (filefind(fname, 23, strn))
  354.         host_send("File already exists!^M^J");
  355.        else
  356.         {
  357.          send_transfer_msg();
  358.          status = receive(option, fname);
  359.         }
  360.       }
  361.      if (status == -2)                        // Carrier lost
  362.       connection_lost = finished_caller = 1;
  363.      else if (status == -1)
  364.       host_send("^GOne or more files not received!^M^J");
  365.     }
  366.    else if (option == 'D')            // User download
  367.     {
  368.      option = host_get_prot();
  369.      if (!option)
  370.       continue;
  371.      host_send("Download what file(s)? ");
  372.      host_input_strn(strn, 48);
  373.      host_send("^M^J");
  374.      if (!strn)
  375.       continue;
  376.      if (access_level != 2)      // if not level 2, keep only name & ext
  377.       fnstrip(strn, 3, fname);
  378.      else
  379.       fname = strn;
  380.  
  381.      if (just_filename(fname))
  382.       {
  383.        strn = host_downloads;
  384.        strcat(strn, fname);
  385.        fname = strn;
  386.       }
  387.  
  388.      if (!filefind(fname, 0, strn))
  389.       {
  390.        host_send("Unable to find any matching file(s)!^M^J");
  391.        continue;
  392.       }
  393.  
  394.      status = 1;
  395.      send_transfer_msg();
  396.      status = send(option, fname);
  397.      if (status == -2)                        // Carrier lost
  398.       connection_lost = finished_caller = 1;
  399.      else if (status == -1)
  400.       host_send("^GOne or more files not received!^M^J");
  401.     }
  402.    else if (option == '~')            // Remote shell
  403.     {
  404.      if (get_port() != 1 && get_port() != 2)
  405.       {
  406.        host_send("Remote Shell not supported on this comm port due to DOS limits!^M^J");
  407.        continue;
  408.       }
  409.  
  410.      if (ask_for_pass(3, shellpass, shellpass) != 0)
  411.       {
  412.        host_send("Type EXIT and then press Return to come back.^M^J");
  413.        if (get_baud() == 300)
  414.         delay(10);
  415.  
  416.        strn = "COM";
  417.        setchr(strn, 3, get_port() + '0'); // get right device name for redirect
  418.  
  419.        if (!local_mode)
  420.         if (redirect_dos(strn) == -1)    // redirect DOS input and output
  421.          continue;
  422.  
  423.        dos("", 0);                    // actually call the shell
  424.  
  425.        if (!local_mode)
  426.         redirect_dos("");         // very important to put things back to norm
  427.       }
  428.     }
  429.    else if (option == '^Z')            // Shut down Host Mode
  430.     {
  431.      host_send("Shut down Host mode. ");
  432.      if (!ask_for_pass(3, shutpass, shutpass))
  433.       continue;
  434.      host_send("Goodbye!^M^J");
  435.      if (carrier_counts)
  436.       hangup();
  437.      ustamp("User shut down Host Mode.", 1, 1);
  438.      finished_caller = 1;
  439.      exit_requested = 1;
  440.     }
  441.   }
  442. }
  443.  
  444. //////////////////////////////////////////////////////////////////////////////
  445.  
  446. host_get_prot()
  447.  
  448. {
  449.  str prot[1];
  450.  
  451.  host_send("^M^JModem7  SEAlink  Xmodem  1k-Xmodem  G-1k-Xmodem  Ymodem  YmodEm-g  Zmodem^M^J");
  452.  host_send("Which protocol? ");
  453.  host_input_strn(prot, 1);
  454.  host_send("^M^J");
  455.  
  456.  if (strposi("MSX1GYEZ", prot, 0) == -1)     // if illegal prot
  457.   prot = "";                                 // return 0
  458.  
  459.  return (toupper(subchr(prot, 0)));
  460.  
  461. }
  462.  
  463. //////////////////////////////////////////////////////////////////////////////
  464.  
  465. send_transfer_msg()
  466.  
  467. {
  468.  host_send("Ready to transfer file(s)... Press Ctrl-X at least twice to abort^M^J");
  469. }
  470.  
  471. //////////////////////////////////////////////////////////////////////////////
  472. // Determine the baud rate once a Carrier Detect Signal has been detected
  473. // Since no characters were read, the 'CONNECT' string should still be
  474. // in the receive buffer.
  475.  
  476. determine_baud()
  477.  
  478. {
  479.  int t3, t12, t24, t96, t192;
  480.  int tmark, stat;
  481.  int new_baud = 0;
  482.  
  483.  printsc("Determining baud... ");
  484.  
  485.  track_free(0);                // clear all existing tracks
  486.  
  487.  t3 = track(conn300, 0);       // check for connect strings
  488.  t12 = track(conn1200, 0);
  489.  t24 = track(conn2400, 0);
  490.  t96 = track(conn9600, 0);
  491.  t192 = track(conn19200, 0);
  492.  
  493.  tmark = timer_start(30);      // wait up to 3 seconds for string
  494.                              
  495.  while (!time_up(tmark))
  496.   {
  497.    if (!carrier())
  498.     {
  499.      track_free(0);            // clear all existing tracks
  500.      return 0;
  501.     }
  502.  
  503.    if (cinp_cnt())
  504.     track_addchr(cgetc());
  505.  
  506.    stat = track_hit(0);
  507.    if (stat == 0)
  508.     continue;
  509.  
  510.    if (stat == t3)
  511.     new_baud = 300;
  512.    else if (stat == t24)
  513.     new_baud = 2400;
  514.    else if (stat == t96)
  515.     new_baud = 9600;
  516.    else if (stat == t192)
  517.     new_baud = 19200;
  518.    else
  519.     new_baud = 1200;
  520.  
  521.    break;                      // have baud rate, get out
  522.   }
  523.  
  524.  if (!new_baud)                // time-up without CONNECT string
  525.   {
  526.    prints("Failed!");
  527.    track_free(0);              // clear all existing tracks
  528.    return 0;     
  529.   }
  530.  
  531.  printn(new_baud);
  532.  prints("");
  533.  set_cparams(new_baud, get_parity(), get_datab(), get_stopb());
  534.  
  535.  track_free(0);                // clear all existing tracks
  536.  return 1;                     // indicate success
  537.  
  538. }
  539.  
  540. //////////////////////////////////////////////////////////////////////////////
  541.  
  542. type_file(str fname)
  543.  
  544. {
  545.  int f;
  546.  str buf[100];
  547.  int ichar, lines_sent = 0;
  548.  
  549.  f = fopen(fname, "r");
  550.  if (!f)
  551.   return -1;
  552.  
  553.  host_send("^M^J");
  554.  
  555.  while (1)
  556.   {
  557.    if (carrier_counts)
  558.     if (!carrier())
  559.      {
  560.       connection_lost = 1;
  561.       finished_caller = 1;
  562.       fclose(f);
  563.       return 0;
  564.      }
  565.  
  566.    if (fgets(buf, 80, f) == -1)
  567.     {
  568.      fclose(f);
  569.      return 1;
  570.     }
  571.  
  572.    host_send(buf);
  573.    host_send("^M^J");
  574.    ++lines_sent;
  575.  
  576.    if (lines_sent >= 22)
  577.     {
  578.      lines_sent = 0;
  579.      host_send("[More]");
  580.      host_input();
  581.  
  582.      if (finished_caller)         // if user inactivity
  583.       {
  584.        fclose(f);
  585.        return 0;
  586.       }
  587.  
  588.      host_send("^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H^H ^H");
  589.     }
  590.  
  591.    while (cinp_cnt())
  592.     {
  593.      ichar = cgetc();
  594.      if (ichar == '^C' || ichar == '^K')
  595.       {
  596.        host_send("^M^J");
  597.        fclose(f);
  598.        return 1;
  599.       }
  600.     }
  601.   }
  602. }
  603.  
  604. //////////////////////////////////////////////////////////////////////////////
  605.  
  606. host_send(str outstr)
  607.  
  608. {
  609.  
  610.  printsc(outstr);
  611.  if (!local_mode)
  612.   cputs(outstr);
  613.  
  614. }
  615.  
  616. //////////////////////////////////////////////////////////////////////////////
  617.  
  618. host_send_c(int chr)
  619.  
  620. {
  621.  
  622.  printc(chr);
  623.  if (!local_mode)
  624.   cputc(chr);
  625.  
  626. }
  627.  
  628. //////////////////////////////////////////////////////////////////////////////
  629.  
  630. host_input_strn(str buf, int maximum)
  631.  
  632. {
  633.  int i = 0, key;
  634.  
  635.  while (1)
  636.   {
  637.    key = host_input();
  638.    if (!key)                 // timeout or user disconnect
  639.     {
  640.      setchr(buf, 0, 0);      // set string to empty
  641.      return 0;               // indicate there is a problem
  642.     }
  643.  
  644.    if (key == '^M')
  645.     break;
  646.    if (key == 127 || key == 8)
  647.     {
  648.      if (i)
  649.       {
  650.        --i;
  651.        host_send_c(key);
  652.       }
  653.      continue;
  654.     }
  655.    if (i < maximum)
  656.     {
  657.      setchr(buf, i, key);
  658.      i = i + 1;
  659.     }
  660.    else
  661.     i = i + 1;
  662.   }
  663.  
  664.  if (i > maximum)
  665.   i = maximum;
  666.  
  667.  setchr(buf, i, '^0');
  668.  
  669.  if (subchr(buf, 0))
  670.   return 1;
  671.  else
  672.   return 0;
  673.  
  674. }
  675.  
  676. //////////////////////////////////////////////////////////////////////////////
  677.  
  678. host_input()
  679.  
  680. {
  681.  int c;
  682.  int t;
  683.  
  684.  t = timer_start(2400);         // 4 minutes inactivity allowed
  685.  
  686.  while (1)
  687.   {
  688.    if (time_up(t) && !direct_connect)
  689.     {
  690.      host_send("^M^J^M^JInactivity period too long. Connection terminated!^M^J");
  691.      if (carrier_counts)
  692.       hangup();
  693.      finished_caller = 1;
  694.      kill_user = 1;
  695.      return 0;
  696.     }
  697.  
  698.    if (carrier_counts)
  699.     if (!carrier())
  700.       {
  701.        prints("^M^JConnection has been lost, call terminated.^M^J");
  702.        connection_lost = 1;
  703.        finished_caller = 1;
  704.        return 0;
  705.       }
  706.  
  707.    if ((c = inkey()) != 0)
  708.     {
  709.      if (c == 27)               // ESC key, sysop wants to exit
  710.       {
  711.        finished_caller = 1;
  712.        exit_requested = 1;
  713.        return 0;
  714.       }
  715.      else if (c == 0x4f00)      // END key, temrinate user
  716.       {
  717.        prints("^M^JUser terminated!");
  718.        ustamp("User terminated!", 1, 1);
  719.        if (carrier_counts)
  720.         hangup();
  721.  
  722.        finished_caller = 1;
  723.        kill_user = 1;
  724.        return 0;
  725.       }
  726.  
  727.      else if (c <= 255)
  728.       {
  729.        if (c != 8 && c != 127)   
  730.         host_send_c(c);
  731.        return c;
  732.       }
  733.     }
  734.  
  735.    if (!local_mode)
  736.     if (cinp_cnt())
  737.      {
  738.       c = cgetc();
  739.       if (c != 8 && c != 127)
  740.        host_send_c(c);
  741.       return c;
  742.      }
  743.   }
  744. }
  745.  
  746. //////////////////////////////////////////////////////////////////////////////
  747.  
  748. ask_for_pass(int maxtries, str pass1, str pass2)
  749.  
  750. {
  751.  int i;
  752.  str strn[8];
  753.  
  754.  for (i = 0; i < maxtries; ++i)
  755.   {
  756.    if (i)
  757.     host_send("Wrong! Try again.^M^J");
  758.    host_send("Password: ");
  759.    host_input_strn(strn, 8);
  760.    host_send("^M^J");
  761.  
  762.    if (finished_caller)
  763.     return 0;
  764.  
  765.    if (!strcmpi(strn, pass1))
  766.     return 1;
  767.  
  768.    if (!strcmpi(strn, pass2))
  769.     return 2;
  770.   }
  771.  
  772.  host_send("No more chances. Access denied.^M^J");
  773.  
  774.  return 0;
  775.  
  776. }
  777.  
  778. //////////////////////////////////////////////////////////////////////////////
  779.  
  780. read_host_config_file()
  781.  
  782. {
  783.  str s[80];
  784.  int f, stat;
  785.  
  786.  s = _telix_dir;
  787.  strcat(s, "HOST.CNF");
  788.  
  789.  f = fopen(s, "r");
  790.  if (!f)
  791.   {
  792.    printsc("Can't open ");
  793.    prints(s);
  794.    return -1;
  795.   }
  796.  
  797.  stat = fgets(s, 80, f);
  798.  if (stat == -1)
  799.   goto got_error;
  800.  pass1 = s;
  801.  
  802.  stat = fgets(s, 80, f);
  803.  if (stat == -1)
  804.   goto got_error;
  805.  pass2 = s;
  806.  
  807.  stat = fgets(s, 80, f);
  808.  if (stat == -1)
  809.   goto got_error;
  810.  shellpass = s;
  811.  
  812.  stat = fgets(s, 80, f);
  813.  if (stat == -1)
  814.   goto got_error;
  815.  shutpass = s;
  816.  
  817.  stat = fgets(s, 80, f);
  818.  if (stat == -1)
  819.   goto got_error;
  820.  host_downloads = s;
  821.  
  822.  stat = fgets(s, 80, f);
  823.  if (stat == -1)
  824.   goto got_error;
  825.  host_uploads = s;
  826.  
  827.  stat = fgets(s, 80, f);
  828.  if (stat == -1)
  829.   goto got_error;
  830.  direct_connect = (toupper(subchr(s, 0)) == 'D');
  831.  
  832.  fclose(f);
  833.  return 1;
  834.  
  835. // jump here if error
  836.  
  837.  got_error:
  838.   fclose(f);
  839.   return -1;
  840.  
  841. }
  842.  
  843. //////////////////////////////////////////////////////////////////////////////
  844.  
  845. check_directories()
  846.  
  847. {
  848.  str s[80];
  849.  int i, a;
  850.  
  851.  // first remove trailing slashes
  852.  
  853.  s = host_uploads;
  854.  i = strlen(s);
  855.  if (i > 0)
  856.   if (subchr(s, i - 1) == '\' || subchr(s, i - 1) == '/')
  857.    setchr(s, i - 1, 0);
  858.  if (s && !(strlen(s) == 2 && subchr(s, 1) == ':'))
  859.   {
  860.    a = fileattr(s);
  861.    if (a == -1 || !(a & 16))
  862.     return 0;                  // not a directory or doesn't exist
  863.   }
  864.  
  865.  s = host_downloads;
  866.  i = strlen(s);
  867.  if (i > 0)
  868.   if (subchr(s, i - 1) == '\' || subchr(s, i - 1) == '/')
  869.    setchr(s, i - 1, 0);
  870.  if (s && !(strlen(s) == 2 && subchr(s, 1) == ':'))
  871.   {
  872.    a = fileattr(s);
  873.    if (a == -1 || !(a & 16))
  874.     return 0;                  // not a directory or doesn't exist
  875.   }
  876.  
  877.  return 1;
  878.  
  879. }
  880.  
  881. //////////////////////////////////////////////////////////////////////////////
  882. // returns TRUE if passed filespec is just a filename. Also handles the
  883. // forward slash as a path separator.
  884.  
  885. just_filename(str filespec)
  886.  
  887. {
  888.  int slash, space;
  889.  
  890.  if (strpos(filespec, ":", 0) != -1)
  891.   return 0;
  892.  if (strpos(filespec, "\", 0) != -1)
  893.   return 0;
  894.  if ((slash = strpos(filespec, "/")) == -1)
  895.   return 1;
  896.  
  897.  space = strpos(filespec, " ");
  898.  if (space == -1)
  899.   return 0;
  900.  if (space < slash)
  901.   return 1;
  902.  
  903.  return 0;
  904.  
  905. }
  906.  
  907. //////////////////////////////////////////////////////////////////////////////
  908. 
  909.